#pragma once
#include "dbng.hpp"

#include "mysql.hpp"
#include "include/wrapper/cef_helpers.h"

#include <memory>

using namespace std;
using namespace ormpp;

struct Role;
struct User;
struct Department;
struct SerialNum;

class DBManager{
    private:
        dbng<mysql> _mysql;
        static shared_ptr<DBManager> _inst;

        DBManager(){
            _mysql.connect("localhost", "root", "123", "uavs");

            ormpp_auto_key key{"id"};
            _mysql.create_datatable<Role>(key);
            _mysql.create_datatable<User>(key);
            _mysql.create_datatable<Department>(key);
            _mysql.create_datatable<SerialNum>(key);
        }
    public:
        static shared_ptr<DBManager> inst(){
            if(_inst.get())return _inst;
            _inst.reset(new DBManager);
            return _inst;
        }
        dbng<mysql> mysql(){return _mysql;}

        template<typename T,typename Arg,typename... Args> 
        constexpr enable_if_t<iguana::is_reflection_v<T>, vector<T>> query(const Arg& s,Args&&... args){
            try{
                return _mysql.query<T>(s,args...);
            }catch(...){
                return vector<T>();
            }
        }
        
        template<typename T, typename... Args>
		constexpr std::enable_if_t<iguana::is_reflection_v<T>, std::vector<T>> query(Args&&... args) {
            try{
                return _mysql.query<T>(args...);
            }catch(...){
                return vector<T>();
            }
        }

        template<typename T, typename... Args>
		constexpr int insert(const std::vector<T>& t, Args&&... args) {
			try{
                return _mysql.insert<T>(t,args...);
            }catch(...){
                return 0;
            }
		}

		template<typename T, typename... Args>
		constexpr int update(const std::vector<T>& t, Args&&... args) {
			try{
                return _mysql.update<T>(t,args...);
            }catch(...){
                return 0;
            }
		}

		template<typename T, typename... Args>
		constexpr int insert(const T& t, Args&&... args) {
			try{
                return _mysql.insert<T>(t,args...);
            }catch(...){
                return 0;
            }
		}

		template<typename T, typename... Args>
		constexpr int update(const T& t, Args&&... args) {
			try{
                return _mysql.query<T>(t,args...);
            }catch(...){
                return 0;
            }
		}

		template<typename T, typename... Args>
		constexpr bool delete_records(Args&&... where_conditon) {
			try{
                return _mysql.delete_records<T>(where_conditon...);
            }catch(...){
                return 0;
            }
		}
};